import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { DraggableList } from "../../scripts/ui/draggableList.js";
import { ComfySettingsDialog } from "../../scripts/ui/settings.js";
import { ComfyDialog, $el } from "../../scripts/ui.js";
// import layuiCss from "./layuiCss.js"
export class Story {
    Parent = null;
    Vue = null;
    Layui = null;
    VueApp = null;
    VueRef = null;
    NodeName = 'comfyui-test-node'
    constructor(parent) {
        this.Parent = parent;
        this.layoutHtml();
    }
    layoutHtml() {
        this.loadVue();
    }

    /**
     *  加载vue
     */
    loadVue() {
        var that = this;
        (async () => {
            var isLoadFile = function (key, resolve, reject) {
                var loadInterval = setInterval(function () {
                    if (typeof key == "string") {
                        if (!window.__CONTAINER_LIST__.hasOwnProperty(key)) {
                            return;
                        }
                    }
                    if (typeof key == 'function') {
                        if (!key()) {
                            return;
                        }
                    }

                    clearInterval(loadInterval);
                    return resolve();
                }, 100);
            }
            await new Promise((resolve, reject) => {
                $el("script", {
                    parent: document.querySelector("head"),
                    src: `/extensions/${this.NodeName}/vue.jss`,
                    type: "text/javascript"
                });
                isLoadFile('Vue', resolve, reject);
            });

            await new Promise((resolve, reject) => {
                $el("script", {
                    parent: document.querySelector("head"),
                    src: `/extensions/${this.NodeName}/layuiVue.jss`,
                    type: "text/javascript"
                });
                isLoadFile('LayuiVue', resolve, reject);
            });

            await new Promise((resolve, reject) => {
                $el("link", {
                    parent: document.querySelector("head"),
                    href: `/extensions/${this.NodeName}/layuiCss.css`,
                    rel: "stylesheet",
                    id: "layuiCss"
                });
                isLoadFile(() => {
                    if (!document.querySelector('#layuiCss')) {
                        return !1;
                    }
                    return !0;
                }, resolve, reject);
            });
            console.log('start init');
            that.initVueApp(window.__CONTAINER_LIST__);
        })();
    }

    initCss() {
        return `
            #storyApp{
                width:100%;
                height:100%;
            }
            .content-switch{
                cursor:pointer;
            }
            .close-content{
                width: 140px !important;
                height: 40px !important;
            }
        `;
    }
    startButton() {
        return `
            <lay-panel>
                <span class="drag-handle" id="storyDrag"></span>
                <lay-space size="md">
                    <lay-tag maxWidth="100px" @click="openWind" style="cursor:pointer;">{{appTitle}}</lay-tag>
                </lay-space>
            </lay-panel>
            <lay-layer :title="appTitle" v-model="storyWind" :shade="false" :area="['30%', '80%']" >
                ${this.storyHtml()}
            </lay-layer>
        `
    }

    storyHtml() {
        return `
            <div class="card-container" id="storyContainer">
                <lay-card>
                    <template v-slot:body>
                        <lay-tab type="brief" allow-close v-model="current6" @change="change6"  @close="closeTab">
                            <lay-tab-item v-for="a in pageList" :key="a" :title="a.title" :id="a.id" :closable="a.closable">
                                <component :is="a.component" v-bind="a" @add-menu="addMenu"></component>
                            </lay-tab-item>
                        </lay-tab>
                    </template>
                </lay-card>
            </div>
            
        `
    }

    initVueApp(container) {
        this.Vue = container['Vue'];
        this.VueRef = this.Vue.ref;
        this.Layui = container['LayuiVue'];
        $el("style", {
            parent: document.querySelector('.zbq-container'),
            innerHTML: this.initCss()
        });
        $el("div.story", {
            parent: this.Parent,
            id: "storyApp",
            innerHTML: this.startButton()
        });
        var that = this;
        var vueAppObject = {
            data() {
                return {
                    appTitle: "故事集",
                    storyList: [],
                    chapterList: [],
                    fieldList: [],
                    current6: that.VueRef("1"),
                    pageList: [
                        { id: '1', title: '故事列表', closable: false, component: "storyCommponent" },
                        // { id: '2', title: '章节列表', closable: true, html: `2` },
                    ],
                    contentSwitch: 1,
                    // 故事集窗口
                    storyWind: false,
                }
            },
            created() {

            },
            methods: {
                openWind() {
                    this.storyWind = true;
                },
                change6: () => {
                },
                closeTab: function (id) {
                    console.log('closeTab', id)
                    var index = -1;
                    for (var i in this.pageList) {
                        var val = this.pageList[i]
                        if (val.id == id) {
                            index = i;
                        }
                    }
                    if (index > -1) {
                        this.pageList.splice(index, 1);
                        return;
                    }
                },
                // 箭头符号的函数，this指向的是全局
                changeContentSwitch() {
                    if (this.contentSwitch == 1) {
                        that.Parent.getElementsByClassName('layui-card-body')[0].style.visibility = "hidden";
                        that.Parent.classList.add("close-content")
                        this.contentSwitch = 2;
                    } else {
                        that.Parent.getElementsByClassName('layui-card-body')[0].style.visibility = "visible";
                        that.Parent.classList.remove("close-content")
                        this.contentSwitch = 1;
                    }

                },
                openRoleWind(e, row) {
                    console.log('openRoleWind', row)
                },
                addMenu(obj) {
                    console.log(obj);
                    var bool = false;
                    for (var i in this.pageList) {
                        var val = this.pageList[i]
                        if (val.id == obj.NovelId) {
                            bool = true;
                        }
                    }
                    if (bool) {
                        this.current6 = obj.NovelId;
                        return;
                    }
                    var menu = { id: obj.NovelId, title: '角色列表【' + obj.Name + '】', closable: true, component: "roleCommponent" }
                    this.pageList.push(menu);
                    this.current6 = obj.NovelId;
                },
            },
            /* setup() {
                var storyData = that.storyList();
                return storyData;
            } */
        }
        const vueApp = this.Vue.createApp(vueAppObject);

        vueApp.use(this.Layui);
        vueApp.mount("#storyApp");

        // 绑定组件
        vueApp.component('storyCommponent', this.storyCommponent());
        vueApp.component('roleCommponent', this.roleCommponent());


        // 拖拽
        this.settings = new ComfySettingsDialog(app);
        this.dragElement(this.Parent, this.settings);

    }

    /* vueAppData() {
        return {
            appTitle: "故事集",
            storyList: [],
            chapterList: [],
            fieldList: [],
            current6: this.VueRef("1"),
            pageList: [
                { id: '1', title: '故事列表', closable: false, component: "test11" },
                { id: '2', title: '章节列表', closable: true, html: `2` },
            ],
        };
    } */


    storyCommponent() {
        var that = this;
        return {
            props: {
                id: Number
            },
            data() {
                return {
                    count: 0
                }
            },
            created() {
                console.log(this.id, this.$attrs)
            },

            template: `
            <lay-form  :pane="true">
                <lay-form-item label="名称" mode="inline">
                <lay-input v-model="storyName"></lay-input>
                </lay-form-item>
            
                <lay-form-item mode="inline" style="width:100px;">
                <lay-button type="primary" @click="queryList">查询</lay-button>
                </lay-form-item>
            </lay-form>
              <lay-table 
              :page="page" 
              :resize="true"
              :height="'100%'"
              :columns="columns" 
              :loading="loading"
              :default-toolbar="true"
              :data-source="dataSource" 
              :autoColsWidth="true"
              v-model:selected-keys="selectedKeys"  
              @change="change"
              @sortChange="sortChange">
            <template #status="{ row }">
              <lay-switch :model-value="row.status" @change="changeStatus($event , row)"></lay-switch>
            </template>
            <template v-slot:toolbar>
              <lay-button size="sm" type="primary" @click="openStory">新增</lay-button>
              <lay-button size="sm" @click="remove">删除</lay-button>
            </template>
            <template v-slot:operator="{ row }">
              <lay-button size="xs" type="primary" @click="openStory(row)">编辑</lay-button>
              
              <lay-dropdown :trigger="['click']" updateAtScroll>
                <lay-button size="xs">更多</lay-button>
                <template #content>
                    <lay-dropdown-menu>
                        <lay-dropdown-menu-item @click="$emit('addMenu', row)">角色</lay-dropdown-menu-item>
                        <lay-dropdown-menu-item>场景</lay-dropdown-menu-item>
                        <lay-dropdown-menu-item @click="storyDelDo(row)">删除</lay-dropdown-menu-item>
                    </lay-dropdown-menu>
                </template>
             </lay-dropdown>
            </template>
            <template v-slot:showImage="{ row }">
                <img v-if="row.Image != ''" :src="row.Image" @click="seeImage(row.Image)" style="width:150px;max-height:150px;">
            </template>
          </lay-table>
          <lay-layer title="编辑故事" v-model="storyLayer" :shade="false" :area="['30%', '80%']">
                <div style="padding:10px;">
                    <lay-form :model="storyData" ref="storyForm"  required>
                        <lay-form-item label="故事名" prop="Name">
                            <lay-input v-model="storyData.Name"></lay-input>
                        </lay-form-item>

                        <lay-form-item label="作者" prop="Author">
                            <lay-input v-model="storyData.Author"></lay-input>
                        </lay-form-item>

                        <lay-form-item label="图片" >
                            <lay-input v-model="storyData.Image"></lay-input>
                        </lay-form-item>

                        <lay-form-item label="" v-if="storyData.Image!=''" >
                            <img :src="storyData.Image" style="width:150px;"/>
                        </lay-form-item>

                        <lay-form-item label="描述" prop="Descript">
                            <lay-textarea placeholder="请输入描述" v-model="storyData.Descript"></lay-textarea>
                        </lay-form-item>

                        <lay-form-item style="text-align: center">
                            <lay-button @click="storySaveDo" type="primary">提交</lay-button>
                        </lay-form-item>
                    </lay-form>    
                </div>
            </lay-layer>
          `,
            setup(props, ctx) {
                /* console.log('attrs', ctx.attrs, ctx.attrs.title); */
                var ref = that.VueRef;
                var reactive = that.Vue.reactive;
                var layer = that.Layui.layer;
                const storyName = ref("");
                const loading = ref(false);
                // 编辑
                const storyLayer = ref(false);
                const storyForm = ref();
                var initData = { Name: "", Author: "", Descript: "", NovelId: 0, "Image": "" };
                const storyData = reactive(initData)
                // 重新赋值，以免被修改
                initData = JSON.parse(JSON.stringify(initData));
                // 选中
                const selectedKeys = ref([]);
                const page = reactive({ current: 1, limit: 10, total: 0 });
                const columns = ref([
                    { title: "操作", width: "100px", customSlot: "operator", key: "operator", ignoreExport: true },
                    { title: "名称", width: "80px", key: "Name" },
                    { title: "图片", width: "150px", key: "showImage", customSlot: "showImage" },
                    { title: "作者", width: "100px", key: "Author" },
                    // { title: "描述", width: "80px", key: "Descript"},
                    // { title: "时间", width: "120px", key: "CreateTime"}
                ]);
                const dataSource = ref([]);
                const change = (page) => {
                    loading.value = true;
                    setTimeout(() => {
                        // dataSource.value = loadDataSource(page.current, page.limit);
                        that.request('/zbq/novel/list', { Page: page.current, Limit: page.limit, StoryName: storyName.value })
                            .then(res => {
                                console.log(res)
                                if (res.code != 0) {
                                    layer.msg(res.msg)
                                    return;
                                }
                                dataSource.value = res.data.List
                                page.total = res.data.Count
                            })
                        loading.value = false;
                    }, 1000);
                }
                // 加载数据
                change(page);

                const sortChange = (key, sort) => {
                    layer.msg(`字段${key} - 排序${sort}, 你可以利用 sort-change 实现服务端排序`)
                }


                const changeStatus = (isChecked, row) => {
                    dataSource.value.forEach((item) => {
                        if (item.id === row.id) {
                            layer.msg("Success", { icon: 1 }, () => {
                                item.status = isChecked;
                            })
                        }
                    })
                }

                const remove = () => {
                    layer.msg(selectedKeys.value, { area: '50%' })
                }


                const openStory = (obj = null) => {
                    storyLayer.value = true;
                    that.setObjData(storyData, initData);
                    if (obj != null) {
                        that.setObjData(storyData, obj);
                        console.log('openStory', storyData, obj);
                    }
                }

                const storySaveDo = () => {
                    storyForm.value.validate((isValidate, model, errors) => {
                        if (!isValidate) {
                            return;
                        }
                        that.request('/zbq/novel/novel_save', storyData).then(res => {
                            console.log(res);
                            if (res.code != 0) {
                                layer.msg(res.msg);
                                return;
                            }
                            layer.msg("保存成功", {
                                icon: 1, time: 1000, end: function () {
                                    console.log(`关闭`)
                                    storyLayer.value = false;
                                    page.current = 1;
                                    change(page)
                                }
                            })

                        })

                    });
                }

                const storyDelDo = (row) => {
                    that.request('/zbq/novel/novel_delete', { NovelId: row.NovelId }).then(res => {
                        console.log(res);
                        if (res.code != 0) {
                            layer.msg(res.msg);
                            return;
                        }
                        layer.msg("删除成功", {
                            icon: 1, time: 1000, end: function () {
                                page.current = 1;
                                change(page)
                            }
                        })

                    })
                }

                const seeImage = function (image) {
                    layer.photos({
                        imgList: [{ src: image, alt: 'layer for vue' }]
                    })
                }

                const queryList = function () {
                    page.current = 1;
                    change(page)
                }

                return {
                    storyName,
                    loading,
                    columns,
                    dataSource,
                    selectedKeys,
                    sortChange,
                    page,
                    change,
                    changeStatus,
                    remove,
                    openStory,
                    storyLayer,
                    storyData,
                    storySaveDo,
                    storyForm,
                    storyDelDo,
                    seeImage,
                    queryList,
                }
            }
        }



    }

    roleCommponent() {
        var that = this;
        return {
            template: `
            <lay-form  :pane="true">
                <lay-form-item label="名称" mode="inline">
                    <lay-input v-model="roleName"></lay-input>
                </lay-form-item>
            
                <lay-form-item mode="inline" style="width:100px;">
                    <lay-button type="primary" @click="queryList">查询</lay-button>
                </lay-form-item>
            </lay-form>
              <lay-table 
              :page="page" 
              :resize="true"
              :height="'100%'"
              :columns="columns" 
              :loading="loading"
              :default-toolbar="true"
              :data-source="dataSource" 
              :autoColsWidth="true"
              v-model:selected-keys="selectedKeys"  
              @change="change"
              @sortChange="sortChange">
            
            <template v-slot:toolbar>
              <lay-button size="sm" type="primary" @click="openEdit">新增</lay-button>
            </template>
            <template v-slot:operator="{ row }">
              <lay-button size="xs" type="primary" @click="openEdit(row)">编辑</lay-button>
              
              <lay-dropdown :trigger="['click']" updateAtScroll>
                <lay-button size="xs">更多</lay-button>
                <template #content>
                    <lay-dropdown-menu>
                        <lay-dropdown-menu-item  @click="$emit('addMenu', 'sssssssssss')">角色</lay-dropdown-menu-item>
                        <lay-dropdown-menu-item>场景</lay-dropdown-menu-item>
                        <lay-dropdown-menu-item @click="delDo(row)">删除</lay-dropdown-menu-item>
                    </lay-dropdown-menu>
                </template>
             </lay-dropdown>
            </template>
            <template v-slot:showImage="{ row }">
                <img v-if="row.RoleImage != ''" :src="row.RoleImage" @click="seeImage(row.RoleImage)" style="width:150px;max-height:150px;">
            </template>
          </lay-table>
          <lay-layer :title="editFormTitle" v-model="editLayer" :shade="false" :area="['30%', '80%']">
                <div style="padding:10px;">
                    <lay-form :model="editFormData" ref="editForm"  required>
                        <lay-form-item label="角色名" prop="RoleName">
                            <lay-input v-model="editFormData.RoleName"></lay-input>
                        </lay-form-item>
                        <lay-form-item label="标签" prop="RoleLabel">
                            <lay-input v-model="editFormData.RoleLabel" placeholder="男女，主角"></lay-input>
                        </lay-form-item>

                        <lay-form-item label="提示词" prop="RolePrompt">
                            <lay-textarea placeholder="角色提示词" v-model="editFormData.RolePrompt"></lay-textarea>
                        </lay-form-item>

                        <lay-form-item label="描述" prop="RoleDesc">
                            <lay-textarea placeholder="请输入描述" v-model="editFormData.RoleDesc"></lay-textarea>
                        </lay-form-item>

                        <lay-form-item label="图片" >
                            <lay-input v-model="editFormData.RoleImage"></lay-input>
                        </lay-form-item>

                        <lay-form-item label="" v-if="editFormData.RoleImage!=''" >
                            <img :src="editFormData.RoleImage" style="width:150px;"/>
                        </lay-form-item>

                        

                        <lay-form-item style="text-align: center">
                            <lay-button @click="saveDo" type="primary">提交</lay-button>
                        </lay-form-item>
                    </lay-form>    
                </div>
            </lay-layer>
          `,
            setup(props, ctx) {
                console.log('attrs', ctx.attrs, ctx.attrs.title);
                var novelId = ctx.attrs.id;
                var ref = that.VueRef;
                var reactive = that.Vue.reactive;
                var layer = that.Layui.layer;
                // 搜索字段
                const roleName = ref("");
                const loading = ref(false);
                // 编辑标题
                const editFormTitle = ref('编辑角色');
                // 编辑
                const editLayer = ref(false);
                // 表单ref
                const editForm = ref();
                var initData = { RoleId: '0', NovelId: novelId, RoleName: "", RolePrompt: "", RoleDesc: "", RoleLabel: '', "RoleImage": "" };
                const editFormData = reactive(initData)
                // 重新赋值，以免被修改
                initData = JSON.parse(JSON.stringify(initData));
                // 选中
                const selectedKeys = ref([]);
                const page = reactive({ current: 1, limit: 10, total: 0 });
                const columns = ref([
                    { title: "操作", width: "100px", customSlot: "operator", key: "operator", ignoreExport: true },
                    { title: "名称", width: "80px", key: "RoleName" },
                    { title: "图片", width: "150px", key: "showImage", customSlot: "showImage" },
                    { title: "标签", width: "100px", key: "RoleLabel" },
                    // { title: "描述", width: "80px", key: "Descript"},
                    // { title: "时间", width: "120px", key: "CreateTime"}
                ]);
                const dataSource = ref([]);
                const change = (page) => {
                    loading.value = true;
                    setTimeout(() => {
                        console.log({
                            Page: page.current,
                            Limit: page.limit,
                            NovelId: novelId,
                            RoleName: roleName.value
                        });
                        that.request('/zbq/novel/role_list', {
                            Page: page.current,
                            Limit: page.limit,
                            NovelId: novelId,
                            RoleName: roleName.value
                        })
                            .then(res => {
                                console.log(res)
                                if (res.code != 0) {
                                    layer.msg(res.msg)
                                    return;
                                }
                                dataSource.value = res.data.List
                                page.total = res.data.Count
                            })
                        loading.value = false;
                    }, 1000);
                }
                // 加载数据
                change(page);



                const openEdit = (obj = null) => {
                    editLayer.value = true;
                    that.setObjData(editFormData, initData);
                    if (obj != null) {
                        that.setObjData(editFormData, obj);
                    }
                }

                const saveDo = () => {
                    editForm.value.validate((isValidate, model, errors) => {
                        if (!isValidate) {
                            return;
                        }
                        that.request('/zbq/novel/role_save', editFormData).then(res => {
                            console.log(res);
                            if (res.code != 0) {
                                layer.msg(res.msg);
                                return;
                            }
                            layer.msg("保存成功", {
                                icon: 1, time: 1000, end: function () {
                                    console.log(`关闭`)
                                    editLayer.value = false;
                                    page.current = 1;
                                    change(page)
                                }
                            })

                        })

                    });
                }

                const delDo = (row) => {
                    that.request('/zbq/novel/role_delete', { RoleId: row.RoleId }).then(res => {
                        console.log(res);
                        if (res.code != 0) {
                            layer.msg(res.msg);
                            return;
                        }
                        layer.msg("删除成功", {
                            icon: 1, time: 1000, end: function () {
                                page.current = 1;
                                change(page)
                            }
                        })

                    })
                }

                const seeImage = function (image) {
                    layer.photos({
                        imgList: [{ src: image, alt: 'layer for vue' }]
                    })
                }

                const queryList = function () {
                    page.current = 1;
                    change(page)
                }

                return {
                    roleName,
                    loading,
                    editFormTitle,
                    editLayer,
                    editForm,
                    editFormData,
                    selectedKeys,
                    page,
                    columns,
                    dataSource,
                    change,
                    openEdit,
                    saveDo,
                    delDo,
                    seeImage,
                    queryList,
                }
            }
        }



    }

    getDataObj() {
        var storyObj = this.getStoryObj();
        var chapterObj = this.getChapterObj();
        var css = `
        <style>
            .story{
                width:100%;
                height:100%;
            }
            #storyApp{
                padding:5px;
                width:100%;
                height:100%;
            }
            .zbq-title{
                font-size:18px;
                font-weight:bold;
                maring-botton:10px;
            }
            .zbq-content{
                width:100%;
                height:100%;
            }
            .c-list{
                padding:5px;
                display:flex;
                flex-direction:column;
                width:100%;
                height:100%;
            }
        </style>`;
        var html = `
        ${storyObj.css}
        ${chapterObj.css}
        <div id="storyApp">
            <div class="zbq-title">
                {{appTitle}}
            </div>
            <div class="zbq-content">
                ${storyObj.html}
                ${chapterObj.html}
            </div>
            <div class="card-container">
            <lay-card title="标题">
                内容
            </lay-card>
            </div>
        </div>
        `;
        var obj = {
            html: css + html,
            methods: Object.assign({}, storyObj.methods, chapterObj.methods)
        }
        return obj
    }

    getStoryObj() {
        var css = `
            <style>
                .story-list{
                    display:flex;
                    flex-direction:column;
                    overflow-y:auto;
                    width:98%;
                    height:80%;
                }
                .story-item{
                    margin-bottom:10px;
                    cursor:pointer;
                }
            </style>
        `;
        var html = `
        <div class="c-list ">
            <div class="story-list">
                <div class="story-item" @dblclick="test1" v-for="(val, key) in storyList">
                    <div v-if="val.Image">
                        <img src="val.Image">
                    </div>
                    <div class="story-info">
                        <div class="story-title">{{val.Title}}</div>
                        <div class="story-other">
                            <span>创建时间：{{val.CreateTime}}</span>
                        </div>
                    </div>
                </div>
            </div>
            <div class="c-page">
                分页
            </div>
        </div>`;
        var obj = {
            css: css,
            html: html,
            methods: {
                test1: () => {
                    console.log(111);
                },
            }
        }
        return obj;
    }

    getChapterObj() {
        var css = `
        <style>
            .chapter-list{
                display:flex;
                flex-direction:column;
                overflow-y:auto;
                width:98%;
                height:80%;
            }
            .chapter-item{
                margin-bottom:10px;
                cursor:pointer;
            }
        </style>
        `;
        var html = `
        <div class="c-list">
            <div class="chapter-list">
                <div class="chapter-item" v-for="(val, key) in chapterList">
                    <div v-if="val.Image">
                        <img src="val.Image">
                    </div>
                    <div class="chapter-info">
                        <div class="chapter-title">{{val.Title}}</div>
                        <div class="chapter-descript">{{val.Descript}}</div>
                        <div class="chapter-other">
                            <span>创建时间：{{val.CreateTime}}</span>
                        </div>
                    </div>
                </div>
            </div>
            <div class="c-page">
                分页
            </div>
        </div>`;
        var obj = {
            css: css,
            html: html
        }
        return obj;
    }

    // 场
    getFieldrObj() {
        var html = `
        <div class="c-list field-list">

        </div>`;
        var obj = {
            html: html
        }
        return obj;
    }

    setObjData(obj, data) {
        for (var k in obj) {
            if (data.hasOwnProperty(k)) {
                obj[k] = data[k];
            }
        }
    }

    async request(url, data) {
        const resp = await api.fetchApi(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)

        })

        // console.log(resp)
        let res = await resp.json()
        return res;
    }

    // 拖拽
    dragElement(dragEl, settings) {
        var posDiffX = 0,
            posDiffY = 0,
            posStartX = 0,
            posStartY = 0,
            newPosX = 0,
            newPosY = 0;
        if (dragEl.getElementsByClassName("drag-handle")[0]) {
            // if present, the handle is where you move the DIV from:
            dragEl.getElementsByClassName("drag-handle")[0].onmousedown = dragMouseDown;
        } else {
            // otherwise, move the DIV from anywhere inside the DIV:
            dragEl.onmousedown = dragMouseDown;
        }

        // When the element resizes (e.g. view queue) ensure it is still in the windows bounds
        const resizeObserver = new ResizeObserver(() => {
            ensureInBounds();
        }).observe(dragEl);

        function ensureInBounds() {
            if (dragEl.classList.contains("comfy-menu-manual-pos")) {
                newPosX = Math.min(document.body.clientWidth - dragEl.clientWidth, Math.max(0, dragEl.offsetLeft));
                newPosY = Math.min(document.body.clientHeight - dragEl.clientHeight, Math.max(0, dragEl.offsetTop));

                positionElement();
            }
        }

        function positionElement() {
            const halfWidth = document.body.clientWidth / 2;
            const anchorRight = newPosX + dragEl.clientWidth / 2 > halfWidth;

            // set the element's new position:
            if (anchorRight) {
                dragEl.style.left = "unset";
                dragEl.style.right = document.body.clientWidth - newPosX - dragEl.clientWidth + "px";
            } else {
                dragEl.style.left = newPosX + "px";
                dragEl.style.right = "unset";
            }

            dragEl.style.top = newPosY + "px";
            dragEl.style.bottom = "unset";

            if (savePos) {
                localStorage.setItem(
                    "Comfy.MenuPosition",
                    JSON.stringify({
                        x: dragEl.offsetLeft,
                        y: dragEl.offsetTop,
                    })
                );
            }
        }

        function restorePos() {
            let pos = localStorage.getItem("Comfy.MenuPosition");
            if (pos) {
                pos = JSON.parse(pos);
                newPosX = pos.x;
                newPosY = pos.y;
                positionElement();
                ensureInBounds();
            }
        }

        let savePos = undefined;
        settings.addSetting({
            id: "Comfy.MenuPosition",
            name: "Save menu position",
            type: "boolean",
            defaultValue: savePos,
            onChange(value) {
                if (savePos === undefined && value) {
                    restorePos();
                }
                savePos = value;
            },
        });

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            // get the mouse cursor position at startup:
            posStartX = e.clientX;
            posStartY = e.clientY;
            document.onmouseup = closeDragElement;
            // call a function whenever the cursor moves:
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();

            dragEl.classList.add("comfy-menu-manual-pos");

            // calculate the new cursor position:
            posDiffX = e.clientX - posStartX;
            posDiffY = e.clientY - posStartY;
            posStartX = e.clientX;
            posStartY = e.clientY;

            newPosX = Math.min(document.body.clientWidth - dragEl.clientWidth, Math.max(0, dragEl.offsetLeft + posDiffX));
            newPosY = Math.min(document.body.clientHeight - dragEl.clientHeight, Math.max(0, dragEl.offsetTop + posDiffY));

            positionElement();
        }

        window.addEventListener("resize", () => {
            ensureInBounds();
        });

        function closeDragElement() {
            // stop moving when mouse button is released:
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }
}